<template>
  <scroll-view :scroll-y="true" @scroll="handleScroll" class="container" id="scrollContainer" :show-scrollbar="true">
    <view class="list" :style="listStyle">
      <view v-for="(item, index) in showList" :key="item.id" :data-index="index" :data-id="item.id" class="list-item">
        <view class="label">id: {{item.id}}---name:{{item.name}}---index:{{index}}</view>
      </view>
    </view>
  </scroll-view>
  <view>
    containerHeight: {{ containerHeight }}
  </view>
  <view>
    pageSize: {{pageSize}}
  </view>
  <view>
    <button @click="addMore">+100</button>
  </view>
</template>

<script setup lang="ts">
  import { ref, onMounted, computed } from 'vue'
  import { onShow } from "@dcloudio/uni-app"
  
  // 子元素定高，大多数场合都可以接受
  const itemHeight = 60
  const defaultPageSize = 10
  const safeArea = 5
  
  const containerHeight = ref(0)
  const pageSize = computed(() => {
    if(containerHeight.value && itemHeight) {
      return Math.ceil(containerHeight.value / itemHeight)
    }
    return defaultPageSize
  })

  onMounted(() => {
    uni.createSelectorQuery().select('#scrollContainer').boundingClientRect((rect) => {
        // console.log(rect); // 这里会返回元素的位置信息（宽高、偏移等）
        containerHeight.value = rect.height
    }).exec();
  })

  const tableList = ref([])
  onShow(() => {
    tableList.value = new Array(500).fill(0).map((item, index) => {
      return {
        id: index,
        name: `name-${index}`
      }
    })
  })
  
  function addMore() {
    let start = tableList.value.length
    let list = new Array(50).fill(0).map((item, index) => {
      return {
        id: start + index,
        name: `name-${start + index}`
      }
    })
    tableList.value = [...tableList.value, ...list]
  }
  
  const startIndex = ref(0)
  const handleScroll = (e) => {
    // console.log(e);
    let _scrollTop = e.detail.scrollTop
    let _startIndex = Math.floor(_scrollTop / itemHeight)
    startIndex.value = Math.max(0, _startIndex - safeArea)
    _scrollTop = startIndex.value * itemHeight
  }
  
  const endIndex = computed(() => {
    return Math.min(startIndex.value + safeArea + pageSize.value + safeArea, tableList.value.length)
  })
  
  const showList = computed(() => {
    return tableList.value.slice(startIndex.value, endIndex.value)
  })
  
  const listStyle = computed(() => {
    return {
      paddingTop: `${startIndex.value * itemHeight}px`,
      paddingBottom: `${(tableList.value.length - endIndex.value) * itemHeight}px`
    }
  })
  
</script>


<style lang="less" scoped>
  .container {
    height: 50vh;
    // background: red;
  }
  
    
  .list-item {
    text-align: center;
    height: 60px;
    display: flex;
    align-items: center;
    background-color: deeppink;
  }
  
  .label {
    width: 100%;
    background-color: yellow;
  }
  
  // .list-item:nth-child(2n) {
  //   background-color: aquamarine;
  // }
</style>